﻿using AIFast.Lakala;
using LaKaLaPay.Request;
using LaKaLaPay.Response;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Text.Json;


namespace LaKaLaPay
{
    public class LakalaOpenPoster
    {
        private static string  MainUrl = "https://s2.lakala.com/api/v3/labs";
        public static LKL_PubRsp<JSAPIPayRsp> MiniAppPay(JSAPIPayReq req, PayConfig config)
        {
            try
            {
                string notiUrl = config.notifyUrl;
                JsonSerializerSettings jsetting = new JsonSerializerSettings();
                jsetting.DefaultValueHandling = DefaultValueHandling.Ignore;


                var pub = new LKL_PubReq<JSAPIPayReq>();
                pub.req_time = DateTime.Now.ToString("yyyyMMddHHmmss");
                pub.out_org_code = config.channelAppId;
                pub.req_data = req;

                string bodyJson = JsonConvert.SerializeObject(pub, jsetting);

                #region 生成签名

                string appid = config.channelAppId;
                string serial_no = config.apiKey;
                String Authorization = GetSign(appid, serial_no, bodyJson, config.certificate);

                #endregion

                Dictionary<string, string> dicHeader = new Dictionary<string, string>();
                dicHeader.Add("Authorization", Authorization);

                string url = MainUrl + "/trans/preorder";

                Dictionary<string, string> rspHeader = new Dictionary<string, string>();

                var rstStr = HttpUtil.HttpPostJson(url, bodyJson, dicHeader, 30, rspHeader);

                if (!ValidSign(rspHeader, rstStr, config.rsaPublicKey))
                {
                    return null;
                }

                var rspMA = JsonConvert.DeserializeObject<LKL_PubRsp<JSAPIPayRsp>>(rstStr);
                return rspMA;


            }
            catch (Exception ex)
            {
                return null;
            }
        }

        private static string GetSign(string appid, string serial_no, string bodyJson, string privateKeyPKCS8)
        {
            /*
                 将分配的appId、证书序列号、时间戳、随机字符串、请求报文拼接。拼接报文一共有5行，每一行为一个参数。行尾以\n（换行符，ASCII编码值为0x0A）结束，包括最后一行。

具体格式如下：
${appid}\n+${serialNo}\n+${timeStamp}\n+${nonceStr}\n+${body}\n
                 */

            string timestamp = TimeStampUtil.GetTimeStampTen().ToString();//10位和13位的都可以 
            string nonce_str = Guid.NewGuid().ToString("N").Substring(12);


            //var tms = DateTimeOffset.Now.ToUnixTimeSeconds();
            //var nonce = Guid.NewGuid().ToString("N")[..12];
            var sign = $"{appid}\n{serial_no}\n{timestamp}\n{nonce_str}\n{bodyJson}\n";
            RSA _priRsa = new RSACryptoServiceProvider();
            _priRsa.ImportFromPem(privateKeyPKCS8);
            var signedBytes = _priRsa.SignData(Encoding.UTF8.GetBytes(sign), HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
            var signature = Convert.ToBase64String(signedBytes);

            string schema = "LKLAPI-SHA256withRSA";
            String token = "appid=\"" + appid + "\",serial_no=\"" + serial_no + "\",timestamp=\"" + timestamp
            + "\",nonce_str=\"" + nonce_str + "\",signature=\"" + signature + "\"";
            String authorization = schema + " " + token;
            return authorization;
        }

        private static bool ValidSign(IDictionary<string, string> rspHeader, string rspBody, string pubCert)
        {
            string appid = "";
            string serial_no = "";
            string timestamp = "";
            string nonce_str = "";
            string rspSign = "";

            foreach (var item in rspHeader)
            {
                if (item.Key == "Lklapi-Appid")
                    appid = item.Value;

                if (item.Key == "Lklapi-Serial")
                    serial_no = item.Value;

                if (item.Key == "Lklapi-Timestamp")
                    timestamp = item.Value;

                if (item.Key == "Lklapi-Nonce")
                    nonce_str = item.Value;

                if (item.Key == "Lklapi-Signature")
                    rspSign = item.Value;
            }

            StringBuilder sc = new StringBuilder();
            sc.AppendFormat("{0}\n", appid);
            sc.AppendFormat("{0}\n", serial_no);
            sc.AppendFormat("{0}\n", timestamp);
            sc.AppendFormat("{0}\n", nonce_str);
            sc.AppendFormat("{0}\n", rspBody);
            string fnstr = sc.ToString();

            byte[] byteCon = Encoding.UTF8.GetBytes(fnstr);

            byte[] byteRspSign = Convert.FromBase64String(rspSign);
            //var rsaPub = RsaUtil.LoadPublicCert(pubCert);
            var cert = new X509Certificate2(Encoding.UTF8.GetBytes(pubCert));
            var rsaPub = cert.GetRSAPublicKey();
            //bool bRst = rsaPub.VerifyData(byteCon, "SHA256", byteRspSign);
            bool bRst = rsaPub.VerifyData(byteCon, byteRspSign, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);

            return bRst;

        }

        public static LKL_PubRsp<OrderQueryRsp> Refund(RefundReq req, PayConfig config)
        {
            try
            {
                JsonSerializerSettings jsetting = new JsonSerializerSettings();
                jsetting.DefaultValueHandling = DefaultValueHandling.Ignore;

                //int refund_fee = VString.TryInt((VString.TryDec(txtRefundAmt.Text) * 100));

                //var req = new RefundReq();
                //req.merchant_no = txtMchNo.Text.Trim();
                //req.term_no = txtTermNo.Text.Trim();
                //req.origin_out_trade_no = txtOutTradeNo.Text;//原商户单号
                //req.out_trade_no = txtOutRefundNo.Text;//退款申请号
                //req.refund_amount = refund_fee.ToString();//退款金额
                //req.refund_reason = "test测试退款";

                //            {
                //                "req_time":"20210907173330",
                //"version":"3.0",
                //"out_org_code":"OP00000003",
                //"req_data":{
                //                    "merchant_no":"822290070111135",
                //    "term_no":"29034705",
                //    "out_trade_no":"wxy2021090700003",
                //    "refund_amount":"1",
                //    "refund_reason":"test测试退款",
                //    "origin_out_trade_no":"wxy2021090700001",
                //    "location_info":{
                //                        "request_ip":"10.176.1.192",
                //        "location":"+37.123456789,-121.123456789"
                //    }
                //                }
                //            }

                var pub = new LKL_PubReq<RefundReq>();
                pub.req_data = req;
                pub.req_time = DateTime.Now.ToString("yyyyMMddHHmmss");
                pub.out_org_code = config.channelAppId;
                pub.version = "3.0";

                string bodyJson = JsonConvert.SerializeObject(pub, jsetting);

                #region 生成签名


                String Authorization = GetSign(config.channelAppId, config.apiKey, bodyJson, config.certificate);

                #endregion

                Dictionary<string, string> dicHeader = new Dictionary<string, string>();
                dicHeader.Add("Authorization", Authorization);

                string url = MainUrl + "/relation/refund";

                Dictionary<string, string> rspHeader = new Dictionary<string, string>();

                var rstStr = HttpUtil.HttpPostJson(url, bodyJson, dicHeader, 30, rspHeader);
                //txtRst.Text = rstStr;
                if (!ValidSign(rspHeader, rstStr,config.rsaPublicKey))
                {
                    //MessageBox.Show("签名验证失败");
                    return null;
                }

                var rspMA = JsonConvert.DeserializeObject<LKL_PubRsp<OrderQueryRsp>>(rstStr);
                var rspM = rspMA.resp_data;

                return rspMA;
  
            }
            catch (Exception ex)
            {
                return null;
            }
        }

        public static LKL_PubRsp<OrderQueryRsp> RefundQuery(OrderQueryReq req, PayConfig config)
        {
            try
            {
                JsonSerializerSettings jsetting = new JsonSerializerSettings();
                jsetting.DefaultValueHandling = DefaultValueHandling.Ignore;

                //int total_fee = VString.TryInt((VString.TryDec(txtAmt.Text.Trim()) * 100));

                //var req = new OrderQueryReq();
                //req.merchant_no = txtMchNo.Text.Trim();
                //req.term_no = txtTermNo.Text.Trim();
                //req.out_trade_no = txtOutRefundNo.Text;//传入退款申请号

                var pub = new LKL_PubReq<OrderQueryReq>();
                pub.req_data = req;

                string bodyJson = JsonConvert.SerializeObject(pub, jsetting);
                bodyJson = bodyJson.Substring(0, bodyJson.Length - 1);
                //空termExtInfo处理
                bodyJson = bodyJson + ",\"termExtInfo\":{}}";

                #region 生成签名

                string appid = config.channelAppId;
                string serial_no = config.apiKey;
                String Authorization = GetSign(appid, serial_no, bodyJson, config.certificate);

                #endregion

                Dictionary<string, string> dicHeader = new Dictionary<string, string>();
                dicHeader.Add("Authorization", Authorization);

                string url = MainUrl + "/labs_order_query";

                Dictionary<string, string> rspHeader = new Dictionary<string, string>();

                var rstStr = HttpUtil.HttpPostJson(url, bodyJson, dicHeader, 30, rspHeader);
                if (!ValidSign(rspHeader, rstStr, config.rsaPublicKey))
                {
                    return null;
                }

                var rspMA = JsonConvert.DeserializeObject<LKL_PubRsp<OrderQueryRsp>>(rstStr);
                var rspM = rspMA.resp_data;
                return rspMA;
                //if (rspM != null)
                //{
                //    //除了退款成功，其它状态未能验证
                //    if (rspM.trade_state == "SUCCESS")
                //    {
                //    }
                //    else if (rspM.trade_state == "DEAL")
                //    {
                //    }
                //    else
                //    {
                //    }
                //}
            }
            catch (Exception ex)
            {
                return null;
            }
        }

    }
}
